﻿Imports System.Xml
''' <summary>
''' 调整数据结构
''' </summary>
'''<remarks>式样书:语法树生成方法-数据结构的调整
'''1.对于PL11中，可以先写BASED数据再写 被BASED数据的情况，这里将BASED数据和实际数据放在2个列表里了
'''  在实际数据里面取一个数据后，把所有BASED这个数据的数据写在下面，同时为了SET ADDRESS后，需要重新绑定变量的原因，也可以考虑维护一张
'''  实体数据和虚拟数据的关系表格
'''  同时，如果BASED的对象不是顶层数据的情况也必须考虑到，上面的步骤可能会遗漏这样的数据。
'''  对于BASED非顶层数据的情况，考虑将这些数据放入LINKAGE里面，在INIT节里面添加SET ADDRESS语句。
'''2.多维数组的时候，且具有COPY句的情况下，层号是个大问题
'''对于       DCL 1 WORK          UNAL STATIC,                           02900000
'''              ......
'''                 3 W_MFKEY             CHAR(17) /*Ｍ／Ｆキー　　　　*/03310000
'''                             INIT(' ');        /*　　　　　　　　　*/03320000
'''        DCL 1 W_MFKEY1      DEF  W_MFKEY,       /*Ｍ／Ｆキー再定義　*/04020000
'''           3 BRNO             PIC'(4)9',        /*店番号　　　　　　*/04030000
'''           3 DATE             PIC'(8)9',        /*データ日付　　　　*/04040000
'''           3 CYCLE            PIC'(1)9',        /*周期コード　　　　*/04050000
'''           3 JYCD             PIC'(1)9',        /*実績／予算コード　*/04060000
'''           3 MXCLS            PIC'(3)9';        /*ＭＸ分類内訳コード*/04070000
'''           DCL MFKEY_YYMM           BASED(ADDR(W_MFKEY1.DATE))        04140000
'''                              PIC'(6)9';                              04150000
'''
'''这样子的嵌套调用，需要维持一张表格，
'''          W_MFKEY1  BASED=WORK ，FILLER = 106
'''          如果发现BASED W_MFKEY1的东西，则认为基于BASED ，且再偏移FILLER
'''</remarks>
Public Class clsJustifyData
    ''' <summary>
    ''' 调整后数据结构
    ''' </summary>
    ''' <remarks></remarks>
    Public Shared NewDataList As New List(Of XmlElement)
    ''' <summary>
    ''' 是否是数组
    ''' </summary>
    ''' <remarks></remarks>
    Public Shared IsArray As Boolean
    ''' <summary>
    ''' 用于一个变量和另一个变量共用内存，而那个变量又和其他变量共用内存的处理
    ''' </summary>
    ''' <remarks></remarks>
    Public Shared BaseRec As New Dictionary(Of String, BaseStructure)
    ''' <summary>
    ''' 基底结构
    ''' </summary>
    ''' <remarks></remarks>
    Public Structure BaseStructure
        ''' <summary>
        ''' 该变量依附于基底名称
        ''' </summary>
        ''' <remarks></remarks>
        Dim strBased As String
        ''' <summary>
        ''' 该变量需要添加FILLER的长度
        ''' </summary>
        ''' <remarks></remarks>
        Dim FillerLength As Integer
    End Structure
    ''' <summary>
    ''' 调整数据结构
    ''' </summary>
    ''' <remarks></remarks>
    Shared Sub JustifyDataStructure()
        '生成数据检索表
        clsDataAssist.GenernateSearchTable()
        '系统用WK_DATA
        '这个变量用来COBOL的数组初始化
        Dim wk_PLI_INIT As XmlElement = mXmlDocument.CreateElement("SINGLEDATA")
        wk_PLI_INIT.SetAttribute("NAME", "WK_PLI_INIT")
        wk_PLI_INIT.SetAttribute("REPEAT", "1")
        wk_PLI_INIT.SetAttribute("TYPE", "FIXED DEC")
        wk_PLI_INIT.SetAttribute("LENGTH", "5")
        mDataNode.WorkList.Add(wk_PLI_INIT)
        '这个变量用来动态调用程序
        Dim wk_PGMNAME As XmlElement = mXmlDocument.CreateElement("SINGLEDATA")
        wk_PGMNAME.SetAttribute("NAME", "WK_PGMNAME")
        wk_PGMNAME.SetAttribute("REPEAT", "1")
        wk_PGMNAME.SetAttribute("TYPE", "CHAR")
        wk_PGMNAME.SetAttribute("LENGTH", "8")
        mDataNode.WorkList.Add(wk_PGMNAME)
        '初始化数组
        NewDataList.Clear()
        '对于具体项目所需要的调整
        clsJRIProject.JustifyDataByJRI()
        'TODO:这里只是对于数据部里面的数据进行调整，不对过程数据进行调整
        '第一次调整，将PL1数组转换为COBOL的数组
        Dim NewDataNode As XmlElement
        For Each mdata As XmlElement In mDataNode.WorkStorageList
            IsArray = False
            NewDataNode = JustifyArray(mdata.Clone)
            '对于数组，进行初始值的处理
            If IsArray Then ArrayInit(NewDataNode)
            NewDataList.Add(NewDataNode)
        Next
        '第二次调整 对于REDIFINE，DEF等的调整
        '1）DEF整理
        mDataNode.WorkStorageList.Clear()
        BaseRec.Clear()
        SetBaseItem()
        NewDataList.Clear()
        '2）有REDIFINE关系的，数据排列位置需要调整
        AdjustBased()
        NewDataList.Clear()
    End Sub
    ''' <summary>
    ''' 调整多维数组
    ''' </summary>
    ''' <param name="SingleDataXml"></param>
    ''' <returns></returns>
    ''' <remarks>语法树生成方法</remarks>
    Shared Function JustifyArray(ByVal SingleDataXml As XmlElement) As XmlElement
        '注释和COPY句的情况，直接返回原来的节点
        If SingleDataXml.Name = "COMMENTLIST" Or SingleDataXml.Name = "INCLUDE" Then
            Return SingleDataXml
        End If
        Dim NewSingleDataXml As XmlElement
        If SingleDataXml.ChildNodes.Count > 0 Then
            NewSingleDataXml = SingleDataXml.CloneNode(False)
            For Each subNode As XmlElement In SingleDataXml.ChildNodes
                'subNode的变化也可能造成结构的破坏，使用SubNode的Clone副本
                '递归调用
                NewSingleDataXml.AppendChild(JustifyArray(subNode.Clone))
            Next
        Else
            NewSingleDataXml = SingleDataXml
        End If
        '多维数组(已经处理过所有子节点)
        If Not (NewSingleDataXml.GetAttribute("REPEAT") = "1" Or _
                NewSingleDataXml.GetAttribute("REPEAT") = String.Empty) Then
            LogWriter.WriteLine("*WARNING: Change MultiArray To TreeData")
            LogWriter.WriteLine("NAME   :" & SingleDataXml.GetAttribute("NAME"))
            LogWriter.WriteLine("REPEAT :" & SingleDataXml.GetAttribute("REPEAT"))
            IsArray = True
            If NewSingleDataXml.GetAttribute("LayNo") = String.Empty Then
                '单条数据
                NewSingleDataXml = SingleArray(NewSingleDataXml)
            Else
                '集团项目
                NewSingleDataXml = TreeArray(NewSingleDataXml)
            End If
            '添加注释
            Dim commentxml As XmlElement = mXmlDocument.CreateElement("COMMENTLIST")
            commentxml.SetAttribute("TEXT", "*WARNING: Change MultiArray To TreeData*")
            NewSingleDataXml.AppendChild(commentxml)
        End If
        Return NewSingleDataXml
    End Function
    ''' <summary>
    ''' 单条数据
    ''' </summary>
    ''' <param name="SingleDataXml"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function SingleArray(ByVal SingleDataXml As XmlElement) As XmlElement
        Dim ArrayLength() As String = SingleDataXml.GetAttribute("REPEAT").Split(",")
        Dim PicTreeNode As XmlElement
        Dim ChildNode As XmlElement
        '单条数据的时候，改为集团数据
        PicTreeNode = mXmlDocument.CreateElement("TREEDATA")
        '添加DUMMY层
        PicTreeNode.SetAttribute("NAME", "DUMMY-" & SingleDataXml.GetAttribute("NAME"))
        PicTreeNode.SetAttribute("LayNo", "1")
        '注释的继承
        PicTreeNode.SetAttribute("COMMMENT", SingleDataXml.GetAttribute("COMMENT"))
        For Each ComtXml As XmlNode In SingleDataXml.ChildNodes
            If ComtXml.Name = "COMMENTLIST" Then
                PicTreeNode.AppendChild(ComtXml.Clone)
            End If
        Next
        If ArrayLength.Length = 1 Then
            '一维数组
            ChildNode = mXmlDocument.CreateElement("SINGLEDATA")
            ChildNode = SingleDataXml.CloneNode(False)
            '防止COPY句层号冲突，使用自然数确定层号
            ChildNode.SetAttribute("LayNo", "2")
            ChildNode.SetAttribute("ArrayLength", "1")
            For Each ComtXml As XmlNode In SingleDataXml.ChildNodes
                If ComtXml.Name <> "COMMENTLIST" Then
                    ChildNode.AppendChild(ComtXml.Clone)
                End If
            Next
            PicTreeNode.AppendChild(ChildNode)
            Return PicTreeNode
        End If
        '多维数组
        For RepeatDeapth As Byte = 0 To ArrayLength.Length - 2
            '第一维开始到N-1维为止
            ChildNode = mXmlDocument.CreateElement("SINGLEDATA")
            If RepeatDeapth = 0 Then ChildNode.SetAttribute("ArrayLength", ArrayLength.Length)
            ChildNode.SetAttribute("NAME", "FILLER")
            ChildNode.SetAttribute("REPEAT", ArrayLength(RepeatDeapth))
            '防止COPY句层号冲突，使用自然数确定层号
            ChildNode.SetAttribute("LayNo", (RepeatDeapth + 2))
            PicTreeNode.AppendChild(ChildNode)
            PicTreeNode = ChildNode
        Next
        'N维定义
        ChildNode = mXmlDocument.CreateElement("SINGLEDATA")
        ChildNode = SingleDataXml.CloneNode(False)
        ChildNode.SetAttribute("NAME", SingleDataXml.GetAttribute("NAME"))
        ChildNode.SetAttribute("REPEAT", ArrayLength(ArrayLength.Length - 1))
        '防止COPY句层号冲突，使用自然数确定层号
        ChildNode.SetAttribute("LayNo", ArrayLength.Length + 1)
        PicTreeNode.AppendChild(ChildNode)
        Do Until PicTreeNode.ParentNode Is Nothing
            PicTreeNode = PicTreeNode.ParentNode
        Loop
        Return PicTreeNode
    End Function
    ''' <summary>
    ''' 集团项目
    ''' </summary>
    ''' <param name="SingleDataXml"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function TreeArray(ByVal SingleDataXml As XmlElement) As XmlElement
        Dim ArrayLength() As String = SingleDataXml.GetAttribute("REPEAT").Split(",")
        Dim PicTreeNode As XmlElement
        Dim ChildNode As XmlElement
        '顶层数据
        If SingleDataXml.GetAttribute("LayNo") = "1" Then
            Return SingleArray(SingleDataXml)
        End If
        '非顶层数组
        If ArrayLength.Length = 1 Then
            '一维数组，不用修改
            Return SingleDataXml
        End If
        '非顶层多维数组
        '第一维数组
        PicTreeNode = mXmlDocument.CreateElement("SINGLEDATA")
        PicTreeNode.SetAttribute("NAME", "FILLER")
        PicTreeNode.SetAttribute("REPEAT", ArrayLength(0))
        PicTreeNode.SetAttribute("LayNo", SingleDataXml.GetAttribute("LayNo"))
        For RepeatDeapth As Byte = 1 To ArrayLength.Length - 2
            '第二维开始到N-1维为止
            ChildNode = mXmlDocument.CreateElement("SINGLEDATA")
            ChildNode.SetAttribute("NAME", "FILLER")
            ChildNode.SetAttribute("REPEAT", ArrayLength(RepeatDeapth))
            '防止COPY句层号冲突，使用自然数确定层号
            ChildNode.SetAttribute("LayNo", (RepeatDeapth + 2 + SingleDataXml.GetAttribute("LayNo")))
            PicTreeNode.AppendChild(ChildNode)
            PicTreeNode = ChildNode
        Next
        'N维定义
        ChildNode = mXmlDocument.CreateElement("SINGLEDATA")
        For Each attr As XmlAttribute In SingleDataXml.Attributes
            ChildNode.SetAttribute(attr.Name, attr.Value)
        Next
        ChildNode.SetAttribute("NAME", SingleDataXml.GetAttribute("NAME"))
        ChildNode.SetAttribute("REPEAT", ArrayLength(ArrayLength.Length - 1))
        '防止COPY句层号冲突，使用自然数确定层号
        ChildNode.SetAttribute("LayNo", (ArrayLength.Length + 1 + SingleDataXml.GetAttribute("LayNo")))
        '子节点的追加
        For Each SubData As XmlElement In SingleDataXml
            'TODO：对于层号的调整
            ChildNode.AppendChild(SubData.Clone)
        Next
        PicTreeNode.AppendChild(ChildNode)
        Do Until PicTreeNode.ParentNode Is Nothing
            PicTreeNode = PicTreeNode.ParentNode
        Loop
        Return PicTreeNode
    End Function
    ''' <summary>
    ''' 集团项目里数组的初始化
    ''' </summary>
    ''' <param name="ArrayDataXml"></param>
    ''' <remarks></remarks>
    Public Shared Sub ArrayInit(ByVal ArrayDataXml As XmlElement)
        If ArrayDataXml.HasChildNodes = False Then Exit Sub
        If IsSimpleInitArray(ArrayDataXml) Then
            SimpleArrayInit(ArrayDataXml)
        Else
            Dim TopName As String = ArrayDataXml.GetAttribute("NAME")
            If TopName.StartsWith("DUMMY-") Then
                TopName = Mid(TopName, 7)
            End If
            SetArrayInit(ArrayDataXml, TopName)
        End If
    End Sub
    ''' <summary>
    ''' 检查节点是否为最简单的带有初始值的数组
    ''' </summary>
    ''' <param name="TestNode"></param>
    ''' <returns></returns>
    ''' <remarks>有且仅有1个实体元素
    ''' 实体元素可能出现在第二层或者第三层，实体元素包含初始值
    ''' 第二层有REPEAT
    ''' </remarks>
    Public Shared Function IsSimpleInitArray(ByVal TestNode As XmlNode) As Boolean
        If TestNode.HasChildNodes = False Then Return False
        '查看第二层的非注释数目
        Dim CheckPoint1 As Byte
        Dim FirstNodeOnLV2 As XmlNode = Nothing
        For Each subNode As XmlNode In TestNode.ChildNodes
            If subNode.Name <> "COMMENTLIST" Then
                CheckPoint1 += 1
                If CheckPoint1 = 1 Then
                    '获取第一个第二层非注释项目
                    FirstNodeOnLV2 = subNode
                End If
            End If
        Next
        '如果第二层的非注释项目数字不是1的话，直接Out
        If CheckPoint1 <> 1 Then Return False
        '如果第二层唯一的非注释项目就是实体元素的话
        If CType(FirstNodeOnLV2, XmlElement).GetAttribute("REPEAT") = String.Empty Then
            Return False
        End If
        If CType(FirstNodeOnLV2, XmlElement).GetAttribute("TYPE") <> String.Empty And _
           CType(FirstNodeOnLV2, XmlElement).GetAttribute("INIT") <> String.Empty Then
            Return True
        End If
        If FirstNodeOnLV2.HasChildNodes = False Then Return False
        '需要考察第3层元素
        CheckPoint1 = 0
        Dim FirstNodeOnLV3 As XmlNode = Nothing
        For Each subNode As XmlNode In FirstNodeOnLV2.ChildNodes
            If subNode.Name <> "COMMENTLIST" Then
                CheckPoint1 += 1
                If CheckPoint1 = 1 Then
                    '获取第一个第二层非注释项目
                    FirstNodeOnLV3 = subNode
                End If
            End If
        Next
        '如果第三层的非注释项目数字不是1的话，直接Out
        If CheckPoint1 <> 1 Then Return False
        '如果第三层唯一的非注释项目就是实体元素的话
        If CType(FirstNodeOnLV3, XmlElement).GetAttribute("TYPE") <> String.Empty And _
           CType(FirstNodeOnLV3, XmlElement).GetAttribute("INIT") <> String.Empty Then
            Return True
        End If
    End Function
    ''' <summary>
    ''' 整条记录为单位，一维数组的情况
    ''' </summary>
    ''' <remarks></remarks>
    Public Shared Sub SimpleArrayInit(ByVal FirstInitNode As XmlElement)
        '寻找第二层实体数据
        Dim DataNode As XmlElement = Nothing
        For Each SubNode As XmlNode In FirstInitNode
            If SubNode.Name <> "COMMENTLIST" Then
                DataNode = SubNode
                Exit For
            End If
        Next
        Dim RepeatTime As Integer = 0
        Dim InitValue As String = String.Empty
        Dim ItemName As String = String.Empty
        '通过第二层的实体数据节点获得REPEAT
        RepeatTime = DataNode.GetAttribute("REPEAT")
        If DataNode.GetAttribute("TYPE") = String.Empty Then
            For Each SubNode As XmlElement In DataNode
                If SubNode.Name <> "COMMENTLIST" Then
                    InitValue = SubNode.GetAttribute("INIT")
                    ItemName = SubNode.GetAttribute("NAME")
                    DataNode = SubNode
                End If
            Next
        Else
            InitValue = DataNode.GetAttribute("INIT")
            ItemName = DataNode.GetAttribute("NAME")
        End If
        DataNode.RemoveAttribute("INIT")
        Dim InitXml As XmlElement = mXmlDocument.CreateElement("TREEDATA")
        Dim strBased As String = String.Empty
        strBased = ItemName & "-FILLER"
        InitXml.SetAttribute("NAME", strBased)
        InitXml.SetAttribute("REPEAT", "1")
        InitXml.SetAttribute("LayNo", "1")
        Dim initArray As String() = InitValue.Split(",")
        If initArray.Length = RepeatTime Then
            For i As Integer = 0 To initArray.Length - 1
                '不复制子节点，不需要注释
                Dim InitValueXml As XmlElement = DataNode.CloneNode(False)
                InitValueXml.SetAttribute("NAME", "FILLER-" & i + 1)
                InitValueXml.SetAttribute("REPEAT", "1")
                InitValueXml.SetAttribute("LayNo", "3")
                InitValueXml.SetAttribute("INIT", initArray(i))
                InitValueXml.SetAttribute("COMMENT", String.Empty)
                InitXml.AppendChild(InitValueXml)
            Next
            CType(FirstInitNode, XmlElement).SetAttribute("BASED", "ADDR(" & strBased & ")")
            NewDataList.Add(InitXml)
        Else
            '使用INIT ' ' 
            '(数字)'文字初始值'
            '(数字)(数字初始值)
            Dim InitChar As String = String.Empty
            If InitValue = "' '" Then
                InitChar = "SPACES"
            End If
            If GetInitRepeat(InitValue) = RepeatTime Then
                InitChar = GetInitValue(InitValue)
            End If
            If Not InitChar.Equals(String.Empty) Then
                'TODO 这种情况下，如果数组的初始值相同的话，也可以直接在数组定义的实体元素的VALUE 里面直接写初始值
                Dim LoopItem As New LoopNode
                LoopItem.LoopFrom = 1
                LoopItem.LoopTo = RepeatTime
                LoopItem.LoopVarName = "WK_PLI_INIT"
                Dim LoopStatementBlock As New clsStatementBlock
                Dim MoveXml As XmlElement
                MoveXml = mXmlDocument.CreateElement("MOVE")
                MoveXml.SetAttribute("SOURCE", InitChar)
                Dim ArrayItemName As String
                ArrayItemName = FirstInitNode.GetAttribute("NAME") & "." & ItemName
                MoveXml.SetAttribute("TARGET", ArrayItemName & "(WK_PLI_INIT)")
                LoopStatementBlock.AddOperation(MoveXml)
                LoopItem.LoopList = LoopStatementBlock
                mDataNode.ActionList.AddLoop(LoopItem)
            Else
                For i As Integer = 0 To initArray.Length - 1
                    '不复制子节点，不需要注释
                    Dim InitValueXml As XmlElement = DataNode.CloneNode(False)
                    InitValueXml.SetAttribute("NAME", "FILLER-" & i + 1)
                    InitValueXml.SetAttribute("REPEAT", "1")
                    InitValueXml.SetAttribute("LayNo", "3")
                    InitValueXml.SetAttribute("INIT", initArray(i))
                    InitValueXml.SetAttribute("COMMENT", String.Empty)
                    InitXml.AppendChild(InitValueXml)
                Next
                'TODO 可以给用户选项，这里可以使用MOVE语句来完成
                For i As Integer = initArray.Length To RepeatTime - 1
                    '不足的节点，进行补完
                    Dim InitValueXml As XmlElement = DataNode.CloneNode(False)
                    InitValueXml.SetAttribute("NAME", "FILLER-" & i + 1)
                    InitValueXml.SetAttribute("REPEAT", "1")
                    InitValueXml.SetAttribute("LayNo", "3")
                    InitValueXml.SetAttribute("COMMENT", String.Empty)
                    InitXml.AppendChild(InitValueXml)
                Next
                CType(FirstInitNode, XmlElement).SetAttribute("BASED", "ADDR(" & strBased & ")")
                NewDataList.Add(InitXml)
            End If
        End If
    End Sub
    ''' <summary>
    ''' 获得(数字)'文字初始值'/(数字)(数字初始值) 数字的部分
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function GetInitRepeat(ByVal InitValue As String) As Integer
        InitValue = InitValue.Trim
        Dim LeftStart As Integer = InitValue.IndexOf("(")
        Dim RightStart As Integer = InitValue.IndexOf(")")
        If LeftStart = 0 And RightStart > 1 Then
            Dim strRtn As String = Mid(InitValue, LeftStart + 2, RightStart - LeftStart - 1)
            If IsNumeric(strRtn) Then
                Return CInt(strRtn)
            End If
        End If
        Return 0
    End Function
    ''' <summary>
    ''' 获得(数字)'文字初始值'/(数字)(数字初始值) 初始值的部分
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function GetInitValue(ByVal InitValue As String) As String
        InitValue = InitValue.Trim
        Dim LeftStart As Integer = InitValue.IndexOf("(")
        Dim RightStart As Integer = InitValue.IndexOf(")")
        If (Mid(InitValue, RightStart + 2, 1) = "(" And Mid(InitValue, InitValue.Length, 1) = ")") Or _
           (Mid(InitValue, RightStart + 2, 1) = "'" And Mid(InitValue, InitValue.Length, 1) = "'") Then
            Return Mid(InitValue, RightStart + 3, InitValue.Length - RightStart - 3)
        End If
        Return String.Empty
    End Function
    ''' <summary>
    ''' 对于不规则的初始值进行赋值
    ''' </summary>
    ''' <param name="TopNode"></param>
    ''' <remarks></remarks>
    Public Shared Sub SetArrayInit(ByVal TopNode As XmlElement, ByVal TopName As String)
        '上一层的REPEAT数
        Dim UpLvRepeatTime As String = TopNode.GetAttribute("REPEAT")
        '遍历所以子元素
        For Each subNode As XmlElement In TopNode.ChildNodes
            If subNode.Name = "COMMENTLIST" Then Continue For
            '具有INIT的项目。这里需要注意，REPEAT可能写在了父节点中，
            '或者写在子节点中
            Dim ThisLvRepeatTime As String = subNode.GetAttribute("REPEAT")
            Dim RealRepeatTime As String = String.Empty
            If UpLvRepeatTime <> String.Empty And UpLvRepeatTime <> "1" Then
                RealRepeatTime = UpLvRepeatTime
            End If
            If ThisLvRepeatTime <> String.Empty And ThisLvRepeatTime <> "1" Then
                RealRepeatTime = ThisLvRepeatTime
            End If
            If subNode.GetAttribute("INIT") <> String.Empty And RealRepeatTime <> String.Empty Then
                Dim InitValue As String = subNode.GetAttribute("INIT")
                Dim initArray As String() = InitValue.Split(",")
                subNode.RemoveAttribute("INIT")
                '使用INIT ' ' 
                '(数字)'文字初始值'
                '(数字)(数字初始值)
                Dim InitChar As String = String.Empty
                If InitValue = "' '" Then
                    InitChar = "SPACES"
                End If
                If GetInitRepeat(InitValue) = RealRepeatTime Then
                    InitChar = GetInitValue(InitValue)
                End If
                If initArray.Length = RealRepeatTime Or InitChar = String.Empty Then
                    'TODO 这种情况下，如果数组的初始值相同的话，也可以直接在数组定义的实体元素的VALUE 里面直接写初始值
                    For i As Integer = 0 To initArray.Length - 1
                        '加入MOVE节点
                        Dim MoveXml As XmlElement
                        MoveXml = mXmlDocument.CreateElement("MOVE")
                        MoveXml.SetAttribute("SOURCE", initArray(i))
                        MoveXml.SetAttribute("TARGET", TopName & "." & subNode.GetAttribute("NAME") & "(" & i + 1 & ")")
                        mDataNode.ActionList.AddOperation(MoveXml)
                    Next
                Else
                    If Not InitChar.Equals(String.Empty) Then
                        Dim LoopItem As New LoopNode
                        LoopItem.LoopFrom = 1
                        LoopItem.LoopTo = RealRepeatTime
                        LoopItem.LoopVarName = "WK_PL1_INIT"
                        Dim LoopStatementBlock As New clsStatementBlock
                        Dim MoveXml As XmlElement
                        MoveXml = mXmlDocument.CreateElement("MOVE")
                        MoveXml.SetAttribute("SOURCE", InitChar)
                        Dim ArrayItemName As String
                        ArrayItemName = TopName & "." & subNode.GetAttribute("NAME")
                        MoveXml.SetAttribute("TARGET", ArrayItemName & "(WK_PL1_INIT)")
                        LoopStatementBlock.AddOperation(MoveXml)
                        LoopItem.LoopList = LoopStatementBlock
                        mDataNode.ActionList.AddLoop(LoopItem)
                    End If
                End If
            End If
            If subNode.ChildNodes.Count > 0 Then
                SetArrayInit(subNode, TopName)
            End If
        Next
    End Sub
    ''' <summary>
    ''' 对于直接是指针BASED属性，添加SET语句
    ''' </summary>
    ''' <remarks></remarks>
    Public Shared Sub SetBaseItem()
        For Each mNode In NewDataList
            '非BASED的情况
            If mNode.GetAttribute("BASED") = String.Empty And mNode.GetAttribute("DEF") = String.Empty Then
                mDataNode.WorkStorageList.Add(mNode.Clone)
                Continue For
            End If
            If mNode.GetAttribute("DEF") <> String.Empty Then
                mNode.SetAttribute("BASED", "ADDR(" & mNode.GetAttribute("DEF") & ")")
                mNode.RemoveAttribute("DEF")
            End If
            If mNode.GetAttribute("BASED").StartsWith("ADDR(") Then
                Dim strBasedValue As String
                strBasedValue = Mid(mNode.GetAttribute("BASED"), 6, mNode.GetAttribute("BASED").Length - 6)
                Dim OrgBaseValue As String = strBasedValue
                Dim IsBaseArrayItem As Boolean = False
                'BASED可能是一个数组的某一项，所有，这里需要进行判断
                If strBasedValue.IndexOf("(") > 0 And strBasedValue.EndsWith(")") Then
                    strBasedValue = Mid(strBasedValue, 1, strBasedValue.IndexOf("("))
                    IsBaseArrayItem = True
                End If
                'ADDR的时候,后面是数据的顶层的话,则什么都不做
                Dim FirstResultXml As XmlElement
                If strBasedValue.Split(".").Length = 1 Then
                    FirstResultXml = clsDataAssist.GetDataItemByDataName(strBasedValue)
                Else
                    'BASED一个成员的情况
                    FirstResultXml = clsDataAssist.GetDataItemByDataPath(strBasedValue)
                End If
                '有一种特例，如果 A BASED(B) B是一个具体数据的话，可能A的属性可以被省略。
                Dim ProCpy As Boolean = True
                If mNode.HasChildNodes Then
                    For Each SubNode As XmlNode In mNode.ChildNodes
                        If SubNode.Name <> "COMMENTLIST" Then
                            '如果有非注释子节点
                            ProCpy = False
                        End If
                    Next
                End If
                '如果有TYPE则不需要
                If mNode.GetAttribute("TYPE") <> String.Empty Then
                    ProCpy = False
                End If
                If ProCpy Then
                    If Not FirstResultXml Is Nothing Then
                        For Each attr As XmlAttribute In FirstResultXml.Attributes
                            Select Case attr.Name
                                Case "NAME", "LayNo", "COMMENT", "INIT"
                                Case Else
                                    mNode.SetAttribute(attr.Name, attr.Value)
                            End Select
                        Next
                    End If
                End If
                Dim FullPath As String = String.Empty
                If Not FirstResultXml Is Nothing Then
                    Dim TempNode As XmlElement = FirstResultXml
                    FullPath = TempNode.GetAttribute("NAME")
                    Do While Not TempNode.ParentNode Is Nothing
                        TempNode = TempNode.ParentNode
                        If TempNode.Name <> "WorkStorage" Then
                            FullPath = TempNode.GetAttribute("NAME")
                        End If
                    Loop
                    '计算总的距离，包括了POS的情况，综合考虑
                    Dim iPos As Integer = 0
                    '叶子节点离根节点的距离
                    If (FirstResultXml.GetAttribute("Distance") = String.Empty OrElse _
                       FirstResultXml.GetAttribute("Distance") = 0) Then
                        iPos = 0
                    Else
                        iPos = FirstResultXml.GetAttribute("Distance")
                    End If
                    'POS的距离
                    If mNode.GetAttribute("POS") <> String.Empty Then
                        iPos = CInt(FirstResultXml.GetAttribute("Distance")) + CInt(mNode.GetAttribute("POS")) - 1
                    End If
                    If iPos = 0 Then
                        '可以使用REDIFINES的方法
                        '将ADDR调整为顶层名称
                        mNode.SetAttribute("BASED", "ADDR(" & FullPath & ")")
                        mDataNode.WorkStorageList.Add(mNode.Clone)
                        '策略1:SET ADDR
                        If IsBaseArrayItem Then
                            Dim InitOpr As XmlElement
                            InitOpr = mXmlDocument.CreateElement("SET")
                            InitOpr.SetAttribute("SOURCE", OrgBaseValue)
                            InitOpr.SetAttribute("TARGET", "ADDRESS  OF  " & mNode.GetAttribute("NAME"))
                            mDataNode.AddSingleInit(InitOpr)
                            '这样的BASED数据作为LINKAGE节，不加入原来数组
                            mNode.RemoveAttribute("BASED")
                            mDataNode.LinkageList.Add(mNode.Clone)
                        End If
                    Else
                        '策略2:填充FILLER(可能是叶子节点，也可能是POS的关系)
                        Dim REFnode As XmlElement = mXmlDocument.CreateElement("TREEDATA")
                        REFnode.SetAttribute("NAME", "REF-" & mNode.GetAttribute("NAME"))
                        REFnode.SetAttribute("LayNo", "1")
                        '如果这个FULLPATH也具有BASED
                        If BaseRec.ContainsKey(strBasedValue.Split(".")(0)) Then
                            REFnode.SetAttribute("BASED", "ADDR(" & BaseRec(strBasedValue.Split(".")(0)).strBased & ")")
                        Else
                            REFnode.SetAttribute("BASED", "ADDR(" & FullPath & ")")
                        End If

                        Dim FILLERnode As XmlElement = mXmlDocument.CreateElement("SINGLEDATA")
                        FILLERnode.SetAttribute("NAME", "FILLER")
                        FILLERnode.SetAttribute("LayNo", "2")
                        FILLERnode.SetAttribute("TYPE", "CHAR")
                        If BaseRec.ContainsKey(strBasedValue.Split(".")(0)) Then
                            FILLERnode.SetAttribute("LENGTH", iPos + BaseRec(strBasedValue.Split(".")(0)).FillerLength)
                        Else
                            FILLERnode.SetAttribute("LENGTH", iPos)
                        End If
                        REFnode.AppendChild(FILLERnode)

                        mNode.SetAttribute("LayNo", "2")
                        mNode.RemoveAttribute("BASED")
                        mNode.RemoveAttribute("DEF")
                        REFnode.AppendChild(mNode.Clone)
                        mDataNode.WorkStorageList.Add(REFnode)

                        '如果以后具有BASED这个节点的东西，
                        '则其实是BASED这个节点的BASED目标
                        '偏移量也需要适当更新
                        Dim T As BaseStructure
                        T.strBased = FullPath
                        T.FillerLength = iPos
                        If Not BaseRec.ContainsKey(mNode.GetAttribute("NAME")) Then
                            BaseRec.Add(mNode.GetAttribute("NAME"), T)
                        End If
                    End If
                Else
                    '顶层数据的情况(SearchDataTable里面没有包含的带有-FILLER，DUMMY-的数据）
                    For Each TopData As XmlElement In NewDataList
                        If TopData.GetAttribute("NAME") = strBasedValue Then
                            mDataNode.WorkStorageList.Add(mNode.Clone)
                        End If
                    Next
                End If
            Else
                '不带有ADDR()的BASED
                'BASED后面直接是指针的情况)直接使用 SET 方法
                Dim InitOpr As XmlElement
                InitOpr = mXmlDocument.CreateElement("SET")
                InitOpr.SetAttribute("SOURCE", mNode.GetAttribute("BASED"))
                InitOpr.SetAttribute("TARGET", "ADDRESS  OF  " & mNode.GetAttribute("NAME"))
                mDataNode.AddSingleInit(InitOpr)
                '这样的BASED数据作为LINKAGE节，不加入原来数组
                mNode.RemoveAttribute("BASED")
                mDataNode.LinkageList.Add(mNode.Clone)
            End If
        Next
    End Sub
    ''' <summary>
    ''' 对于BASED的全局整理
    ''' </summary>
    ''' <remarks></remarks>
    Public Shared Sub AdjustBased()
        '遍历WorkStroage数据，找到一个没有BASED的实际数据，
        For Each mData In mDataNode.WorkStorageList
            If mData.GetAttribute("BASED") = String.Empty Then
                NewDataList.Add(mData.Clone)
                For Each mData2 In mDataNode.WorkStorageList
                    Dim BasedName As String = mData.GetAttribute("NAME")
                    If BasedName.StartsWith("DUMMY-") Then
                        BasedName = Mid(BasedName, 7)
                    End If
                    If mData2.GetAttribute("BASED") = "ADDR(" & BasedName & ")" Then
                        NewDataList.Add(mData2.Clone)
                    End If
                Next
            End If
        Next
        '可能出现数据是REDIFINE一个LINKAGE里面数据的情况
        '例如一个数据要REDIFINE另一个数据，而那个数据是REDIFINE指针的情况
        Dim LinkageTemp As New List(Of XmlElement)
        For Each mData In mDataNode.LinkageList
            LinkageTemp.Add(mData.Clone)
            For Each mData2 In mDataNode.WorkStorageList
                Dim BasedName As String = mData.GetAttribute("NAME")
                If BasedName.StartsWith("DUMMY-") Then
                    BasedName = Mid(BasedName, 7)
                End If
                If mData2.GetAttribute("BASED") = "ADDR(" & BasedName & ")" Then
                    LinkageTemp.Add(mData2.Clone)
                End If
            Next
        Next
        mDataNode.WorkStorageList.Clear()
        For Each DataNode As XmlNode In NewDataList
            mDataNode.WorkStorageList.Add(DataNode)
        Next
        mDataNode.LinkageList.Clear()
        For Each DataNode As XmlNode In LinkageTemp
            mDataNode.LinkageList.Add(DataNode)
        Next
    End Sub
End Class
